<template>
    <div ref="ref">
        <el-form-item
            :label="props.label"
            :prop="props.prop"
            label-position="top"
            class="param-config-form-item"
            :rules="rules"
        >
            <el-table :data="tableData" border style="width: 100%">
                <el-table-column label="序号" type="index" width="60" align="center" :resizable="false" />
                <el-table-column label="参数配置" :resizable="false">
                    <template #default="{ row }">
                        <div class="fields">
                            <el-select placeholder="类型" style="width: 100px" v-model="row.type">
                                <!--                                <el-option label="模型属性" value="ATTRIBUTE" />-->
                                <el-option label="参数" value="PARAM" />
                            </el-select>
                            <template v-if="row.type === 'ATTRIBUTE'">
                                <el-tree-select
                                    :class="{ error: !row.objectName }"
                                    v-model="row.objectName"
                                    placeholder="模型"
                                    style="width: 170px"
                                    :data="modelTree"
                                    :render-after-expand="false"
                                    :loading="modelTreeRequest.loading.value"
                                    :filterable="true"
                                    :check-strictly="true"
                                    popper-class="model-tree-select-popper"
                                    highlight-current
                                    @change="val => onModelChange(val, row)"
                                />
                                <el-select
                                    :class="{ error: !row.attrName }"
                                    placeholder="属性"
                                    style="width: 170px"
                                    v-model="row.attrName"
                                    filterable
                                    @change="val => onAttributeChange(val, row)"
                                >
                                    <el-option
                                        v-for="item in attributeListMap[row.objectName]"
                                        :key="item.id"
                                        :label="item.displayName"
                                        :value="item.attributeName"
                                    />
                                </el-select>
                            </template>
                            <el-input
                                :class="{ error: !row.paramName }"
                                placeholder="变量名"
                                style="width: 170px"
                                v-model="row.paramName"
                                maxlength="50"
                            />
                            <el-input
                                :class="{
                                    error: !row.paramId,
                                    'not-unique error':
                                        row.paramId && tableData.filter(item => item.paramId === row.paramId).length > 1
                                }"
                                placeholder="标识符"
                                style="width: 170px"
                                v-model="row.paramId"
                                maxlength="50"
                                @update:modelValue="formInstance?.clearValidate([props.prop])"
                            />
                            <template v-if="row.type === 'PARAM'">
                                <el-button
                                    link
                                    :class="{ error: !row.paramType }"
                                    :type="row.paramType ? 'primary' : 'danger'"
                                    @click="() => onShowUISchemaModel(row)"
                                >
                                    定义参数({{ row.paramType ? '已定义' : '未定义' }})
                                </el-button>
                            </template>
                        </div>
                    </template>
                </el-table-column>
                <el-table-column prop="zip" width="60" align="center" v-if="!props.disabled">
                    <template #header>
                        <el-button :icon="Plus" type="primary" style="width: 24px" @click="addItem" />
                    </template>
                    <template #default="{ $index }">
                        <el-button :icon="Minus" type="danger" style="width: 24px" @click="removeItem($index)" />
                    </template>
                </el-table-column>
            </el-table>
        </el-form-item>
    </div>
</template>

<script setup lang="ts">
import { Minus, Plus } from '@element-plus/icons-vue';
import { showPopupBox, tryJsonParse } from '@great/utils';
import UISchemaModal from './UISchemaModal.vue';
import { useRequest } from 'vue-request';
import { modelThingService } from '@great/services';
import { formContextKey } from 'element-plus';

interface IProps {
    label: string;
    prop: string;
    modelDetail: Record<string, any>;
    attributeTypeList: Record<string, any>;
    disabled?: boolean;
}

const props = defineProps<IProps>();
const model = defineModel<string>();
const tableData = reactive<any[]>(tryJsonParse(model.value, []));
const modelTree = ref<any[]>([]);
const attributeListMap = ref({});
const elementRef = useTemplateRef('ref');
const formInstance = inject(formContextKey);

onMounted(() => {
    tableData.forEach(item => {
        if (item.type === 'ATTRIBUTE') {
            onModelChange(item.objectName);
        }
    });
});

const rules = reactive([
    {
        validator: (rule: any, value: any, callback: any) => {
            if (elementRef.value?.querySelector('.not-unique')) {
                return callback(new Error('请确保标识符唯一'));
            }
            if (elementRef.value?.querySelector('.error')) {
                return callback(new Error('请完善参数配置'));
            }
            return callback();
        },
        trigger: 'manual'
    }
]);

const modelTreeRequest = useRequest(
    () => {
        return modelThingService.getComponentList({
            objectName: props.modelDetail?.objectName
        });
    },
    {
        onSuccess: result => {
            modelTree.value = formatModelTreeData(result.data);
        }
    }
);

function formatModelTreeData(list: any = []): any[] {
    const uniqueMap = new Map();
    list.forEach(item => {
        if (!uniqueMap.has(item.objectName)) {
            uniqueMap.set(item.objectName, {
                value: item.objectName,
                label: item.displayName,
                children: item.components ? formatModelTreeData(item.components) : []
            });
        }
    });
    return Array.from(uniqueMap.values());
}

function addItem() {
    tableData.push({
        type: 'PARAM'
    });
    formInstance?.clearValidate([props.prop]);
}
function removeItem(index: number) {
    tableData.splice(index, 1);
}

async function onModelChange(objectName, row?: any) {
    if (row) {
        row.attrName = undefined;
    }
    if (!attributeListMap.value[objectName]) {
        const result = await modelThingService.attribute.getList({
            objectName,
            size: 1000000
        });
        attributeListMap.value[objectName] = result.data.records || [];
    }
}
function onShowUISchemaModel(row: any) {
    showPopupBox(UISchemaModal, {
        val: {
            paramType: row.paramType,
            definition: row.definition
        },
        callback: ({ paramType, definition }) => {
            row.paramType = paramType;
            row.definition = definition;
        }
    });
}

function onAttributeChange(val: string, row: any) {
    const attr = attributeListMap.value[row.objectName].find(item => item.attributeName === val);
    if (attr) {
        row.paramName = attr.displayName;
        row.paramId = attr.attributeName;
    }
}

watch(tableData, a => {
    model.value = JSON.stringify(tableData);
    nextTick(() => {
        if (!elementRef.value?.querySelector('.error')) {
            formInstance?.clearValidate([props.prop]);
        }
    });
});
</script>

<style scoped lang="scss">
.fields {
    display: flex;
    gap: 10px;
    align-items: center;
}
</style>
<style lang="scss">
.model-tree-select-popper {
    .el-tree {
        width: 240px !important;
    }
}
.param-config-form-item.is-error {
    .el-form-item__content {
        border: none;
        border-radius: 0;
        padding: 0;
    }
    .el-select__wrapper,
    .el-input__wrapper {
        box-shadow: 0 0 0 1px var(--el-border-color) inset !important;
    }

    .el-input.error {
        .el-input__wrapper {
            box-shadow: 0 0 0 1px var(--el-color-danger) inset !important;
        }
    }
    .el-select.error {
        .el-select__wrapper {
            box-shadow: 0 0 0 1px var(--el-color-danger) inset !important;
        }
    }
}
</style>
